{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 👁️‍🗨️ Alpha-Factory v1 – Cross-Industry AGENTIC α-AGI  \n",
    "## _(Google Colab, self-contained)_\n",
    "\n",
    "**What you get in < 10 minutes**\n",
    "\n",
    "* 🪄 Five domain agents (finance, biotech, climate, mfg, policy) orchestrated by `backend/orchestrator.py`\n",
    "* 🏋️ Continuous PPO fine-tuning that *hot-reloads* weights via a new `/agent/&lt;id&gt;/update_model` API\n",
    "* 🔐 Guard-rails (MCP), ed25519 prompt signing, policy deny-list\n",
    "* 📊 Prometheus **9090** & Grafana **3000** exposed through public *ngrok* URLs\n",
    "* ⚡ 30-second k6 load-test to prove antifragility\n",
    "* 📴 Works offline (Mixtral-8×7B GGML) or online (OpenAI key)\n",
    "\n",
    "> **Paste an `OPENAI_API_KEY` below for better quality,** or leave blank to run fully offline."
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "env" },
   "source": [
    "OPENAI_API_KEY = \"\"  # ← 🔑  put your key here or leave empty"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "code",
   "metadata": { "id": "01-setup" },
   "source": [
    "%%bash\n",
    "set -euo pipefail\n",
    "REPO=AGI-Alpha-Agent-v0\n",
    "if [ ! -d \"$REPO/.git\" ]; then\n",
    "  echo '📥 cloning repo …'\n",
    "  git clone --depth 1 https://github.com/MontrealAI/AGI-Alpha-Agent-v0.git $REPO\n",
    "fi\n",
    "cd $REPO\n",
    "\n",
    "echo '🔧 installing Python deps …'\n",
    "pip install -q -r alpha_factory_v1/requirements-colab.txt  # lightweight agent deps\n",
    "pip install -q ray[default]==2.10.0 uvicorn fastapi pyngrok ctransformers==0.2.27 k6-python subprocess-tee\n",
    "\n",
    "# ─── runtime artefacts ──────────────────────────────────────────────────\n",
    "mkdir -p alpha_factory_v1/{keys,policies,continual,adapters}\n",
    "\n",
    "ssh-keygen -t ed25519 -N '' -q -f alpha_factory_v1/keys/agent_key <<<y || true\n",
    "PUB=$(cat alpha_factory_v1/keys/agent_key.pub)\n",
    "\n",
    "cat > alpha_factory_v1/.env <<EOF\n",
    "ALPHA_FACTORY_MODE=cross_industry\n",
    "OPENAI_API_KEY=${OPENAI_API_KEY}\n",
    "OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1}\n",
    "AGENTS_ENABLED=finance_agent biotech_agent climate_agent manufacturing_agent policy_agent\n",
    "PROMPT_SIGN_PUBKEY=${PUB}\n",
    "EOF\n",
    "\n",
    "cat > alpha_factory_v1/policies/redteam.json <<'JSON'\n",
    "{\"id\":\"af_v1_guard\",\"patterns_deny\":[\"(?i)breakout\",\"(?i)leak\",\"(?i)privileged\"],\"max_tokens\":2048}\n",
    "JSON\n",
    "\n",
    "# ─── offline LLM (Mixtral) if no key ───────────────────────────────────\n",
    "if [ -z \"${OPENAI_API_KEY}\" ]; then\n",
    "  pip install -q sentencepiece\n",
    "  python - <<'PY'\n",
    "from ctransformers import AutoModelForCausalLM\n",
    "AutoModelForCausalLM.from_pretrained(\n",
    "  \"TheBloke/Mixtral-8x7B-Instruct-GGML\",\n",
    "  model_file=\"mixtral-8x7b-instruct.ggmlv3.q4_K_M.bin\",\n",
    "  local_files_only=False)\n",
    "PY\n",
    "fi"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ⚙️ Patch orchestrator: add `/update_model` hot-reload endpoint"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "02-patch" },
   "source": [
    "%%bash\n",
    "apply_patch() {\n",
    "python - <<'PY'\n",
    "import importlib, textwrap, pathlib, inspect\n",
    "src = pathlib.Path('AGI-Alpha-Agent-v0/alpha_factory_v1/backend/orchestrator.py')\n",
    "code = src.read_text()\n",
    "if 'update_model' in code:\n",
    "    print('✅ update_model already present'); raise SystemExit\n",
    "insertion = textwrap.dedent('''\\n@router.post(\"/agent/{agent_id}/update_model\")\\nasync def update_model(agent_id: str, file: bytes = File(...)):\\n    if agent_id not in AGENT_REGISTRY:\\n        raise HTTPException(status_code=404, detail=\"agent not found\")\\n    import tempfile, zipfile, io\\n    with tempfile.TemporaryDirectory() as td:\\n        zf = zipfile.ZipFile(io.BytesIO(file)); zf.extractall(td)\\n        AGENT_REGISTRY[agent_id].load_weights(td)\\n    return {\"status\":\"ok\"}\\n''')\n",
    "marker = '# === ROUTES ==='\n",
    "idx = code.index(marker) + len(marker)\n",
    "new_code = code[:idx] + insertion + code[idx:]\n",
    "src.write_text(new_code)\n",
    "print('🚀 patched orchestrator with hot-reload endpoint')\n",
    "PY\n",
    "}\n",
    "apply_patch"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🚀 Launch orchestrator, agents, Ray & mock adapters (background)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "03-launch" },
   "source": [
    "%%bash --bg\n",
    "cd AGI-Alpha-Agent-v0/alpha_factory_v1\n",
    "ray start --head --dashboard-host 0.0.0.0 --port 6379 --dashboard-port 8265 &>/dev/null &\n",
    "uvicorn backend.orchestrator:app --host 0.0.0.0 --port 8000 &>/dev/null &\n",
    "\n",
    "# tiny PubMed & Carbon adapters\n",
    "python - <<'PY' &>/dev/null &\n",
    "from fastapi import FastAPI; import uvicorn, random\n",
    "app=FastAPI(); @app.get('/')\n",
    "def root(): return {\"msg\":\"ok\"}\n",
    "uvicorn.run(app,host='0.0.0.0',port=8005)\n",
    "PY\n",
    "python - <<'PY' &>/dev/null &\n",
    "from fastapi import FastAPI; import uvicorn\n",
    "app=FastAPI(); @app.get('/co2')\n",
    "def co2(): return {\"ppm\":420.42}\n",
    "uvicorn.run(app,host='0.0.0.0',port=8010)\n",
    "PY"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🔗 Expose Grafana & Prometheus with `pyngrok`"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "04-ngrok" },
   "source": [
    "from pyngrok import ngrok, conf\n",
    "conf.get_default().region = 'us'\n",
    "grafana = ngrok.connect(3000, 'http'); prom = ngrok.connect(9090, 'http')\n",
    "print('Grafana  →', grafana.public_url)\n",
    "print('Prometheus →', prom.public_url)"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🏋️ Quick k6 load-test (20 VUs × 30 s)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "05-k6" },
   "source": [
    "%%bash\n",
    "cat > k6.js <<'JS'\n",
    "import http from 'k6/http'; import {sleep} from 'k6';\n",
    "export let options = {vus:20,duration:'30s'};\n",
    "const A=['finance_agent','biotech_agent','climate_agent','manufacturing_agent','policy_agent'];\n",
    "export default function(){\n",
    "  const a=A[Math.floor(Math.random()*A.length)];\n",
    "  http.post(`http://127.0.0.1:8000/agent/${a}/skill_test`,JSON.stringify({ping:Math.random()}),{headers:{'Content-Type':'application/json'}});\n",
    "  sleep(0.05);\n",
    "}\n",
    "JS\n",
    "k6 run k6.js"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ♻️ Continuous PPO trainer (runs async)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "06-trainer" },
   "source": [
    "%%bash --bg\n",
    "python AGI-Alpha-Agent-v0/alpha_factory_v1/continual/ppo_trainer.py"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ✅ Smoke-probe orchestrator + sample agent call"
   ]
  },
  {
   "cell_type": "code",
   "metadata": { "id": "07-health" },
   "source": [
    "import requests, time, pprint, json, os\n",
    "for _ in range(20):\n",
    "  try:\n",
    "    if requests.get('http://127.0.0.1:8000/healthz').status_code==200:\n",
    "      print('orchestrator healthy'); break\n",
    "  except: pass; time.sleep(2)\n",
    "resp=requests.post('http://127.0.0.1:8000/agent/finance_agent/skill_test',json={'ping':123}).json()\n",
    "pprint.pp(resp)"
   ],
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "### 🎉 All set!\n",
    "\n",
    "* Use the **Grafana** link above (`admin / admin`) to explore dashboards (import JSON if blank)\n",
    "* Rewards tune automatically; edit `rubric.json` in `continual/` and rerun the trainer cell\n",
    "* Adapt this notebook to plug in your own domain adapters or extra agents"
   ]
  }
 ],
 "metadata": {
  "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" },
  "language_info": { "name": "python", "version": "" }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
